package amq.demo;

import java.io.File;
import java.util.Date;
import java.util.List;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;

import lang.JLTool;
import lang.utils.Ictclas4jSeg;

import org.apache.activemq.ActiveMQConnectionFactory;

import amq.demo.thds.SQThd;
import amq.utils.GlobalAMQ;
import amq.utils.enums.ELangCode;
import flib.util.TimeStr;
import flib.util.Tuple;

public class SentConsumer1 implements Runnable{
	public boolean isStop = false;
	String brokerURI;
	JLTool jlt;
	ConnectionFactory connectionFactory;  
    Connection connection = null;  
    Session session = null;
    SQThd sqThd = null;
	
	public SentConsumer1(String bui)
	{
		this.brokerURI = bui;
	}
	
	protected void sayHi()
	{
		MessageProducer producer = null;		
		try
		{			
			Destination destination = session.createQueue(GlobalAMQ.SayHiTopic);
			producer = session.createProducer(destination);
	        producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
	        TextMessage message = session.createTextMessage(String.format("%s:hi", this.getClass().getName()));
	        message.setStringProperty("Topic", GlobalAMQ.QueryTopic);
			producer.send(message);
			System.out.printf("\t[%s] Say Hi...\n", this.getClass().getName());
		}
		catch(JMSException e)
		{
			e.printStackTrace();
		}
		finally
		{
			if(producer!=null) 
			{
				try{producer.close();}catch(Exception e){}
			}
		}
	}
	
	protected void sayBye()
	{
		MessageProducer producer = null;		
		try
		{			
			Destination destination = session.createQueue(GlobalAMQ.SayHiTopic);
			producer = session.createProducer(destination);
	        producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
	        TextMessage message = session.createTextMessage(String.format("%s:bye", this.getClass().getName()));
	        message.setStringProperty("Topic", GlobalAMQ.QueryTopic);
			producer.send(message);
			System.out.printf("\t[%s] Say Bye...\n", this.getClass().getName());
		}
		catch(JMSException e)
		{
			e.printStackTrace();
		}
		finally
		{
			if(producer!=null) 
			{
				try{producer.close();}catch(Exception e){}
			}
		}
	}
	
	protected void _response(List<Tuple> rtnList, String dest, String tid)
	{
		MessageProducer producer = null;		
		try
		{			
			Destination destination = session.createQueue(dest);
			producer = session.createProducer(destination);
	        producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
	        TextMessage message = null;
	        
			// tuple(Rule_ID,Category,Hit_Part,Correction, IRule)
			if(rtnList.size()>0)
			{
				message = session.createTextMessage("Fail");
				message.setBooleanProperty("Correct", false);
				message.setLongProperty("TimeStamp", new Date().getTime());
				message.setStringProperty("TID", tid);
				message.setStringProperty("ServiceName", this.getClass().getName());
				Tuple t = rtnList.get(0);
				message.setStringProperty("Category", (String)t.get(1));			
				message.setStringProperty("Reason", (String)t.get(0));
				message.setStringProperty("Suggestion", (String)t.get(3));
			}
			else
			{
				message = session.createTextMessage("Pass");
				message.setBooleanProperty("Correct", true);
				message.setLongProperty("TimeStamp", new Date().getTime());
				message.setStringProperty("ServiceName", this.getClass().getName());
				message.setStringProperty("TID", tid);
			}
			producer.send(message);
			System.out.printf("\t[%s] Send answer back to Queue:'%s'!\n", this.getClass().getName(), destination);
		}
		catch(JMSException e)
		{
			e.printStackTrace();
		}
		finally
		{
			if(producer!=null) 
			{
				try{producer.close();}catch(Exception e){}
			}
		}
	}
	
	@Override
	public void run() {				  
        Destination destination;  
        MessageConsumer consumer = null;  
        TextMessage message = null;  
        boolean useTransaction = false;  
        try {  
        	// 0) Start Service Query Thread
        	sqThd = new SQThd(brokerURI, this.getClass().getName(), GlobalAMQ.QueryTopic, ELangCode.SimpleChinese);
        	new Thread(sqThd).start();
        	
        	// 1) Prepare JLTool
        	jlt = new JLTool(new File("grammar_simp_chinese.xml")); // Loading LanguageTool rules
        	
        	// 2) Start AMQ Producer        	
        	System.out.printf("\t[%s] Listening to Topic:'%s'...\n", this.getClass().getName(), SentProducer.QueryTopic);
            connectionFactory = new ActiveMQConnectionFactory(brokerURI);  
            connection = connectionFactory.createConnection();  
            connection.start();  
            session = connection.createSession(useTransaction,  
                    Session.AUTO_ACKNOWLEDGE);  
            destination = session.createTopic(GlobalAMQ.QueryTopic);
            consumer = session.createConsumer(destination);
            sayHi();
            while(!isStop)
            {
            	message = (TextMessage) consumer.receive(1000);  
                if(message!=null) {
                	String line = message.getText();
                	String tid = message.getStringProperty("TID").trim();
                	String replyTo = message.getStringProperty("ReplyTo");
                	System.out.printf("\t[%s] Received message:\n%s\n", this.getClass().getName(), message);                	
                	System.out.printf("\t\tUID: %s\n", message.getStringProperty("UID"));
                	System.out.printf("\t\tTID: %s\n", tid);
                	System.out.printf("\t\tReplyTo: %s\n", replyTo);
                	System.out.printf("\t\tSENT: %s\n", line);
                	long st = System.currentTimeMillis();
                	String pos_term_pairs = Ictclas4jSeg.SegSentWithSC(line, ":");
        			List<Tuple> rtnList = jlt.evaluate(pos_term_pairs);
        			System.out.printf("\t[%s] Eval '%s'...%s (%s)\n", this.getClass().getName(), line, 
        					          rtnList.size()>0?"Fail":"Pass", TimeStr.ToStringFrom(st));
        			for(Tuple t:rtnList) System.out.printf("\t\t%s\n", t.get(3)); // Show correction if any
        			_response(rtnList, replyTo, tid);
                }
                
            }                        
        } catch (JMSException jmsEx) {  
  
        } finally {  
            try{
            	sayBye();
            	System.out.printf("\t[%s] Stop listening to Topic:'%s'...\n", this.getClass().getName(), SentProducer.QueryTopic);
            	consumer.close();  
                session.close();  
                connection.close();  
                sqThd.isStop = true;
                sqThd = null;
            } catch(Exception e){}
        }  
        System.out.printf("\t[%s] Bye!\n", this.getClass().getName());        
	}

	
	/**
	 * BD: Sentence Topic Consumer1 - Using Rules From LangTool To Judge Sentence.
	 * @param args
	 */
	public static void main(String[] args) throws Exception{
		if(args.length==0)
		{
			System.out.printf("\t[Info] Please give Connector URI! (ex 'tcp://localhost:61616')\n");
			return;
		}
		SentConsumer1 sc1 = new SentConsumer1(args[0]);
		new Thread(sc1).start();
		
		File stop = new File("STOP");
	    while(true)
	    {
	    	if(stop.exists()) break;
	    	Thread.sleep(5000);
	    }
		sc1.isStop = true;
		System.out.printf("\t[Info] Exit %s...\n", sc1.getClass().getName());
	}
}
